package 课上练习0420_scala_method$$class

/**
 * 类的构造器
 */
object Scala_04Class extends App{
  val d = new Dog("拉布拉多", 10, 100)
//  d.weight --消失了
  val d1 = new Dog1("复制")

  val d2 = Dog2("金毛") // 测试伴生对象生成对象
}

/**
 * 构造函数
 * 1、主构造器，放在类名的后面。
 * 2、主构造器特点：
 *  2.1 会执行类里面的所有语句，如下面的haha
 *  2.2 如果主构造器中的属性没有使用var或者val修饰，属性就不会自动保存成字段，对象创建完成后，反编译后发现属性直接消失，
 *      如果在方法中至少使用了一次，那么会保存下来，变为私有final属性字段，scala中相当于private [this] val name
 */
class Dog (var name: String, var age: Int, weight: Int){
  self => // 给this起别名，self等价于this，必须放在第一行
  println("haha")// 测试主构造器调用时会不会执行这一句

  //

  /**
   * 辅助构造器
   * 1、当字段已经在主构造器中定义完成，辅助构造器中不能加var；
   * 2、辅助构造器的声明不能和主构造器的声明一致，会发生错误（构造器重复）；
   * 3、辅助构造器的第一行必须是以主构造器或者另一个辅助构造器的调用开始;
   * 4、辅助构造器无法定义新的成员变量，即无法添加var
   */
  def this(name: String) {  // 错误写法：def this(var name: String) { ... }
    // 注意这里使用weight不算使用，反编译后weight还是会消失！！
    this(name, -1, -1)
  }

  def useWeight() = {
    // 测试weight字段使用后是否会消失，需反编译查看
//    println(weight)
  }
}

// 私有的主构造器，不能被外界直接调用，相当于添加了两个属性
// 当我们将主构造器私有化后，不能再通过主构造器创建对象，只能借助于辅助构造器继续创建对象
class Dog1 private (var name: String, var height: Int) {
  def this(name: String) {
    this(name, 100)
  }
}
// 私有的主构造器属性，getter和setter以及自身都成了private的了，规则和类内属性一样的用
class Dog2 (private var name: String) {}


object Dog2 {
  // 伴生对象辅助生成对象
  def apply(name: String): Dog2 = new Dog2(name)
}

